import { expect, test } from 'vitest'

import { functionType } from './FunctionType'
import { genericParameter } from './GenericParameter'
import { namedType } from './NamedType'
import { parameter } from './Parameter'
import { stringify } from './stringify'

const A = namedType('A')
const B = namedType('B')

test('basic', () => {
  expect(stringify(functionType())).toMatchInlineSnapshot(`"() => void"`)
})

test('with return type', () => {
  const func = functionType().setReturnType(A)
  expect(stringify(func)).toMatchInlineSnapshot(`"() => A"`)
})

test('with parameter', () => {
  const func = functionType().addParameter(parameter('param', A))
  expect(stringify(func)).toMatchInlineSnapshot(`"(param: A) => void"`)
})

test('with multiple parameters', () => {
  const func = functionType().addParameter(parameter('param1', A)).addParameter(parameter('param2', B))
  expect(stringify(func)).toMatchInlineSnapshot(`"(param1: A, param2: B) => void"`)
})

test('with generic parameter', () => {
  const func = functionType().addGenericParameter(genericParameter('T'))
  expect(stringify(func)).toMatchInlineSnapshot(`"<T>() => void"`)
})

test('with multiple generic parameters', () => {
  const func = functionType().addGenericParameter(genericParameter('T')).addGenericParameter(genericParameter('U'))
  expect(stringify(func)).toMatchInlineSnapshot(`"<T, U>() => void"`)
})
